#include<mutex>
using namespace std;

namespace code
{
	template<class T>
	class shared_ptr
	{
	public:
		//1.RAII
		shared_ptr(T* ptr = nullptr)
			:_ptr(ptr)
			, _pcount(new int(1))
			, _pmutex(new mutex)
		{}

		~shared_ptr()
		{
			Release();
		}
		//2.像指针一样使用
		T& operator*() { return *_ptr; }

		T* operator->() { return _ptr; }

		T* get()const { return _ptr; }

		//3.引用计数解决拷贝构造问题
		shared_ptr(const shared_ptr<T>& sp)
			:_ptr(sp._ptr)
			, _pcount(sp._pcount)
			, _pmutex(sp._pmutex)
		{
			//拷贝 + 计数++
			AddRef();
		}

		shared_ptr<T>& operator=(const shared_ptr<T>& sp)
		{
			//不给自己赋值
			if (_ptr != sp._ptr)
			{
				Release();

				_ptr = sp._ptr;
				_pcount = sp._pcount;
				_pmutex = sp._pmutex;

				AddRef();
			}
			return *this;
		}
		void AddRef()
		{
			_pmutex.lock();
			++(*_pcount);
			_pmutex.unlock();
		}

		void Release()
		{
			_pmutex->lock();
			bool DeleteMutex = false;

			if (--(*_pcount) == 0 && _ptr)
			{
				delete _ptr;
				delete _pcount;
				DeleteMutex = true;
			}
			_pmutex->unlock();

			if (DeleteMutex)delete _pmutex;

		}

		//4.weak_ptr解决重复引用问题
		template<class T>
		class weak_ptr
		{
		public:
			weak_ptr()
				:_ptr(nullptr)
			{}

			weak_ptr(const shared_ptr<T>& sp)
				:_ptr(sp.get())
			{}

			T& operator*() { return *_ptr; }

			T* operator->() { return _ptr; }

		private:
			T* _ptr;
		};

	private:
		T* _ptr;
		int* _pcount;
		mutex* _pmutex;
	};
}